---
title: API Access
description: Learn how to access and use Latitude's API to run your prompts.
---

For detailed endpoint specifications, request/response schemas, and the ability to try out API calls directly, please refer to the [Interactive API Documentation](https://gateway.latitude.so/api-docs/).

We recommend checking the SDK docs section in case you're looking for a specific language or framework.

## Latitude HTTP API Documentation

This guide explains how to use the Latitude HTTP API to interact with the Prompt Manager and run AI-powered conversations.

### Authentication

All API requests require authentication. Include your API key in the `Authorization` header of your HTTP requests:

```
Authorization: Bearer YOUR_API_KEY
```

### Base URL

The base URL for API requests depends on your environment:

`https://gateway.latitude.so/api/v3`

### Rate Limiting

The API enforces rate limits based on your API key to ensure fair usage and prevent abuse.

**Limits:**

Rate limits are enforced based on your subscription plan. The following limits apply:

- **Hobby Plan:**
  - 10 requests per second

- **Team Plan:**
  - 166 requests per second (10000 requests per minute)

- **Enterprise Plan:**
  - 500 requests per second (30000 requests per minute)

Contact sales to request a custom rate limit in the enterprise plan.

When the rate limit is exceeded, the following headers are included in the response to help you manage your request rate:

- `Retry-After`: Indicates the number of seconds to wait before making a new request.
- `X-RateLimit-Limit`: The maximum number of requests allowed in the current period.
- `X-RateLimit-Remaining`: The number of requests remaining in the current period.
- `X-RateLimit-Reset`: The timestamp when the rate limit will reset.

**Example Headers:**

```http
Retry-After: 60
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 999
X-RateLimit-Reset: 1729399082482
```

These headers are sent with every request to help you monitor and adjust your request rate accordingly.

### Endpoints

#### 1. Get a Document

Retrieve a specific prompt by its path.

**Endpoint:** `GET /projects/{projectId}/versions/{versionUuid}/documents/{path}`

**Path Parameters:**

- `projectId`: Your project ID (required)
- `versionUuid`: Version UUID (required, optional for SDK's defaults to 'live')
- `path`: Path to the document (required)

**Response:**

The response contains the existing document details along with its configuration.

**Response Body:**

```json
{
  "id": "document-id",
  "documentUuid": "document-uuid",
  "path": "path/to/document",
  "content": "Document content",
  "resolvedContent": "Document content without comments",
  "contentHash": "content-hash",
  "commitId": "commit-id",
  "deletedAt": "deleted-at",
  "createdAt": "created-at",
  "updatedAt": "updated-at",
  "mergedAt": "merged-at",
  "projectId": "project-id",
  "config": {
    "provider": "Provider name",
    "model": "Model name"
  }
}
```

#### 2. Get or Create a Document

**Endpoint:** `POST /projects/{projectId}/versions/{versionUuid}/documents/get-or-create`

**Path Parameters:**

- `projectId`: Your project ID (required)
- `versionUuid`: Version UUID (required, optional for SDK's defaults to 'live')

**Request Body:**

```json
{
  "path": "path/to/document",
  "prompt": "Your prompt here"
}
```

- `path`: Path to the document (required)
- `prompt`: Prompt to use for the document (optional, defaults to empty)

**Response:**

The response contains the created (or existing) document details along with its configuration.

**Response Body:**

```json
{
  "id": "document-id",
  "documentUuid": "document-uuid",
  "path": "path/to/document",
  "content": "Document content",
  "resolvedContent": "Document content without comments",
  "contentHash": "content-hash",
  "commitId": "commit-id",
  "deletedAt": "deleted-at",
  "createdAt": "created-at",
  "updatedAt": "updated-at",
  "mergedAt": "merged-at",
  "projectId": "project-id",
  "config": {
    "provider": "Provider name",
    "model": "Model name"
  }
}
```

#### 3. Create or Update a Document

Create a new document or update an existing one in a single operation. This endpoint provides more control than `get-or-create`, including the ability to update live commits with the `force` flag.

**Endpoint:** `POST /projects/{projectId}/versions/{versionUuid}/documents/create-or-update`

**Path Parameters:**

- `projectId`: Your project ID (required)
- `versionUuid`: Version UUID (required, optional for SDK's defaults to 'live')

**Request Body:**

```json
{
  "path": "path/to/document",
  "prompt": "Your prompt here",
  "force": false
}
```

- `path`: Path to the document (required)
- `prompt`: Content of the document (required)
- `force`: Allow modifications to live/merged commits (optional, defaults to `false`)

**Behavior:**

- If the document **does not exist** at the specified path, it will be created
- If the document **already exists** at the path, it will be updated with the new content
- By default, modifications are only allowed on draft commits (not live/merged)
- When `force: true`, allows creating or updating documents in live commits (use with caution)

<Warning>
  Using `force: true` allows modifying production prompts directly. This should
  only be used for emergency hotfixes or controlled production updates. For
  normal development workflows, use draft commits.
</Warning>

**Response:**

The response contains the created or updated document details along with its configuration.

**Response Body:**

```json
{
  "id": "document-id",
  "documentUuid": "document-uuid",
  "path": "path/to/document",
  "content": "Document content",
  "resolvedContent": "Document content without comments",
  "contentHash": "content-hash",
  "commitId": "commit-id",
  "deletedAt": "deleted-at",
  "createdAt": "created-at",
  "updatedAt": "updated-at",
  "mergedAt": "merged-at",
  "projectId": "project-id",
  "config": {
    "provider": "Provider name",
    "model": "Model name"
  }
}
```

**Error Handling:**

If you try to modify a live commit without the `force` flag, the API returns a 400 status code:

```json
{
  "name": "BadRequestError",
  "message": "Cannot modify a merged commit. Use force=true to allow modifications to the live commit.",
  "errorCode": "BadRequestError",
  "details": {}
}
```

**Use Cases:**

- **Single API call for upsert operations**: No need to check if a document exists before creating/updating
- **Programmatic prompt updates**: Update prompts from your CI/CD pipeline or automation scripts
- **Emergency hotfixes**: Use `force: true` to quickly fix production prompts when needed
- **Batch operations**: Efficiently create or update multiple documents in a loop

**Example: Update with Force Flag**

```bash
curl -X POST "https://gateway.latitude.so/api/v3/projects/123/versions/live/documents/create-or-update" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "path": "production/emergency-fix",
    "prompt": "---\nprovider: openai\nmodel: gpt-4\n---\n\nFixed prompt content",
    "force": true
  }'
```

#### 4. Create a Version (Commit)

Create a new draft version (commit) for a project. Versions allow you to manage changes to your prompts before publishing them to production.

**Endpoint:** `POST /projects/{projectId}/versions`

**Path Parameters:**

- `projectId`: Your project ID (required)

**Request Body:**

```json
{
  "name": "Version name or title"
}
```

- `name`: Name/title for the new version (required)

**Response:**

The response contains the created version (commit) details.

**Response Body:**

```json
{
  "id": 123,
  "uuid": "version-uuid",
  "projectId": 456,
  "message": "Version name or title",
  "authorName": "Author name",
  "authorEmail": "author@example.com",
  "authorId": 789,
  "createdAt": "2024-01-01T00:00:00.000Z",
  "updatedAt": "2024-01-01T00:00:00.000Z",
  "status": "draft",
  "parentCommitUuid": "parent-version-uuid"
}
```

**Use Cases:**

- **Create draft versions**: Start working on prompt changes in isolation
- **Version control**: Track different iterations of your prompts
- **CI/CD integration**: Programmatically create versions from your deployment pipeline

**Example:**

```bash
curl -X POST "https://gateway.latitude.so/api/v3/projects/123/versions" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Feature: Add Spanish language support"
  }'
```

#### 5. Publish a Version (Commit)

Publish a draft version (commit) to make it the live/production version. This merges the draft changes and assigns it a version number.

**Endpoint:** `POST /projects/{projectId}/versions/{versionUuid}/publish`

**Path Parameters:**

- `projectId`: Your project ID (required)
- `versionUuid`: UUID of the draft version to publish (required)

**Request Body:**

```json
{
  "title": "Optional updated title",
  "description": "Optional description or release notes"
}
```

- `title`: Optional title for the published version (if not provided, uses existing title)
- `description`: Optional description or release notes for the published version

**Response:**

The response contains the published version (commit) details with a version number and merged timestamp.

**Response Body:**

```json
{
  "id": 123,
  "uuid": "version-uuid",
  "projectId": 456,
  "message": "Published version title",
  "authorName": "Author name",
  "authorEmail": "author@example.com",
  "authorId": 789,
  "createdAt": "2024-01-01T00:00:00.000Z",
  "updatedAt": "2024-01-01T00:00:00.000Z",
  "status": "merged",
  "parentCommitUuid": "parent-version-uuid"
}
```

<Warning>
  Publishing a version makes it the live/production version. All documents in
  the published version become the active versions accessible via the API. Make
  sure to test your changes thoroughly before publishing.
</Warning>

**Use Cases:**

- **Deploy to production**: Publish tested prompt changes to make them live
- **Release management**: Track which version is currently in production
- **Automated deployments**: Publish versions from CI/CD pipelines after successful tests

**Example:**

```bash
curl -X POST "https://gateway.latitude.so/api/v3/projects/123/versions/abc-123-def-456/publish" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Feature: Add Spanish language support",
    "description": "Added support for Spanish language queries with improved accuracy"
  }'
```

**Error Handling:**

If you try to publish a version that is already published or doesn't exist, the API returns an appropriate error:

```json
{
  "name": "BadRequestError",
  "message": "Cannot publish: version is not a draft",
  "errorCode": "BadRequestError",
  "details": {}
}
```

#### 6. Run a Document

Run a specific document (prompt) with optional parameters.

**Endpoint:** `POST /projects/{projectId}/versions/{versionUuid}/documents/run`

**Path Parameters:**

- `projectId`: Your project ID (required)
- `versionUuid`: Version UUID (required, optional for SDK's defaults to 'live')

**Request Body:**

```json
{
  "path": "path/to/document",
  "parameters": {
    "key1": "value1",
    "key2": "value2"
  },
  "stream": false,
  "background": false,
  "userMessage": "Optional user message",
  "customIdentifier": "optional-custom-id",
  "tools": ["tool1", "tool2"]
}
```

- `stream`: Optional boolean parameter (defaults to `false`). When set to true, the response will be a stream of Server-Sent Events (SSE). If false, a single JSON response containing the last event is returned.
- `background`: Optional boolean parameter (defaults to `false`). When set to true, the request is enqueued for background processing and returns immediately with a conversation UUID.
- `userMessage`: Optional string to start the conversation with a user message.
- `customIdentifier`: Optional string for custom identification of the run.
- `tools`: Optional array of tool names to enable for this run.

**Response:**

- If `background` is `true`: Returns immediately with a conversation UUID for background processing:

```json
{
  "uuid": "conversation-uuid"
}
```

- If `stream` is `true`: The response is a stream of Server-Sent Events (SSE). Check out the [Streaming Events](/guides/api/streaming-events) guide for more information about the specific events you can expect.

- If `stream` is `false`: A single JSON response is returned with the final event (typically the chain-complete event) in the following structure:

```json
{
  "uuid": string,
  "conversation": Message[],
  "response": {
    "streamType": "text" | "object",
    "usage": {
      "promptTokens": number,
      "completionTokens": number,
      "totalTokens": number
    },
    "text": string,
    "object": object | undefined,
    "toolCalls": ToolCall[]
    "cost": number
}
```

<Note>
  Message follows the [PromptL format](/promptl/getting-started/introduction).
</Note>

<Note>
ToolCall has the following format:

```typescript
type ToolCall = {
  id: string
  name: string
  arguments: Record<string, unknown>
}
```

</Note>

#### 7. Chat

The previously described `POST /projects/{projectId}/versions/{versionUuid}/documents/run` endpoint can also be used to continue a conversation. Notice all events contain a `uuid` field that represents that conversation with the AI. You can use this uuid to continue the conversation.

**Endpoint:** `POST /conversations/{conversationUuid}/chat`

**Path Parameters:**

- `conversationUuid`: UUID of the conversation

**Request Body:**

- Messages follow the [PromptL format](/promptl/getting-started/introduction). If you're using a different method to run your prompts, you'll need to format your messages accordingly.

```json
{
  "messages": [
    {
      "role": "user" | "system" | "assistant",
      "content": [
        {
          "type": "text",
          "text": "message content"
        }
      ],
    }
  ],
  "stream": true
}
```

- `stream`: Optional boolean parameter (defaults to `false`). When set to true, the response will be a stream of Server-Sent Events (SSE). If false, a single JSON response containing the last event is returned. Check out the [Streaming Events](/guides/api/streaming-events) guide for more information about the specific events you can expect.

<Note>
  Message follows the [PromptL format](/promptl/getting-started/introduction).
</Note>

**Response:**
The response is a stream of Server-Sent Events (SSE) or a single JSON response containing the final event, similar to the "Run a Document" endpoint.

Check out the [Streaming Events](/guides/api/streaming-events) guide for more information about the specific events you can expect.

#### 8. Get a Conversation

Retrieve a conversation by its UUID. This endpoint returns the complete conversation history including all messages.

**Endpoint:** `GET /conversations/{conversationUuid}`

**Path Parameters:**

- `conversationUuid`: UUID of the conversation (required)

**Response:**

The response contains the conversation UUID and the complete conversation history as an array of messages.

**Response Body:**

```json
{
  "uuid": "conversation-uuid",
  "conversation": [
    {
      "role": "user" | "system" | "assistant",
      "content": [
        {
          "type": "text",
          "text": "message content"
        }
      ]
    }
  ]
}
```

<Note>
  Message follows the [PromptL format](/promptl/getting-started/introduction).
</Note>

**Error Handling**

If the conversation is not found, the API returns a 404 status code with an error message:

```json
{
  "name": "NotFoundError",
  "message": "Conversation not found",
  "errorCode": "NotFoundError",
  "details": {}
}
```

#### 9. Stop a Conversation

Stop an active conversation that is currently running.

**Endpoint:** `POST /conversations/{conversationUuid}/stop`

**Path Parameters:**

- `conversationUuid`: UUID of the conversation

**Request Body:**

No request body is required for this endpoint.

**Response:**

This endpoint returns a 200 status code when the conversation is successfully stopped.

#### 10. Attach to a Conversation

Attach to an active conversation to receive its ongoing output.

**Endpoint:** `POST /conversations/{conversationUuid}/attach`

**Path Parameters:**

- `conversationUuid`: UUID of the conversation

**Request Body:**

```json
{
  "stream": false
}
```

- `stream`: Optional boolean parameter (defaults to `false`). When set to true, the response will be a stream of Server-Sent Events (SSE). If false, a single JSON response containing the final event is returned.

**Response:**

- If `stream` is `true`: The response is a stream of Server-Sent Events (SSE). Check out the [Streaming Events](/guides/api/streaming-events) guide for more information about the specific events you can expect.

- If `stream` is `false`: A single JSON response is returned with the final event in the following structure:

```json
{
  "uuid": "conversation-uuid",
  "conversation": [
    {
      "role": "user" | "system" | "assistant",
      "content": [
        {
          "type": "text",
          "content": "message content"
        }
      ]
    }
  ],
  "response": {
    "streamType": "text" | "object",
    "usage": {
      "promptTokens": 10,
      "completionTokens": 15,
      "totalTokens": 25
    },
    "text": "response text",
    "object": {},
    "toolCalls": []
    "cost": number
  }
}
```

**Error Handling**

The API uses standard HTTP status codes. In case of an error, the response body will contain an error message:

```json
{
  "error": {
    "message": "Error description"
  }
}
```

#### 11. Annotate a Log

Add an annotation (evaluation score) to a log.

**Endpoint:** `POST /conversations/{conversationUuid}/evaluations/{evaluationUuid}/annotate`

**Path Parameters:**

- `conversationUuid`: UUID of the conversation to annotate
- `evaluationUuid`: UUID of the evaluation to use

**Request Body:**

```json
{
  "score": 2,
  "versionUuid": "version-uuid", // optional
  "metadata": {
    "reason": "The output is not relevant to the prompt"
  }
}
```

**Response:**

```json
{
  "uuid": "annotation-uuid",
  "score": 2,
  "normalizedScore": 0.5,
  "metadata": {
    "reason": "The output is not relevant to the prompt"
  },
  "hasPassed": false,
  "error": "optional-error-message",
  "versionUuid": "version-uuid"
}
```

#### 12. Create Log Entry

Create a log entry for a document.

**Endpoint:** `POST /projects/{projectId}/versions/{versionUuid}/documents/logs`

**Path Parameters:**

- `projectId`: Your project ID (required)
- `versionUuid`: Version UUID (required, optional for SDK's defaults to 'live')

**Request Body:**

- Messages follow the [PromptL format](/promptl/getting-started/introduction). If you're using a different method to run your prompts, you'll need to format your messages accordingly.

```json
{
  "path": "path/to/document",
  "messages": [
    {
      "role": "user" | "system" | "assistant",
        {
          "type": "text",
          "content": string
        }
    }
  ],
  "response": string
}
```

**Response:**

```json
{
  "id": "document-id",
  "uuid": "log-uuid",
  "documentUuid": "document-uuid",
  "commitId": "commit-id",
  "resolvedContent": "Document content without comments",
  "contentHash": "content-hash",
  "parameters": {},
  "customIdentifier": "custom-identifier",
  "duration": "duration",
  "source": "source",
  "createdAt": "created-at",
  "updatedAt": "updated-at"
}
```
